Skip to content

fix: zero wildcard matches for --required-files is not an error; literal non-matches emit SLNX020#68

Draft
Copilot wants to merge 3 commits intomainfrom
copilot/fix-required-files-error-handling
Draft

fix: zero wildcard matches for --required-files is not an error; literal non-matches emit SLNX020#68
Copilot wants to merge 3 commits intomainfrom
copilot/fix-required-files-error-handling

Conversation

Copy link
Copy Markdown
Contributor

Copilot AI commented Apr 7, 2026

Changes the behaviour of --required-files when a pattern matches zero files, distinguishing between wildcard and literal patterns:

  • Wildcard patterns (containing * or ?) with zero matches → silently skipped, no error
  • Literal patterns (no wildcards, e.g. unknownfile.md) with zero matches → SLNX020 (RequiredFileDoesntExistOnSystem) error

Changes

  • SlnxCollector.cs: Restore the matched.Count == 0 branch but guard the SLNX020 error behind !HasWildcard — wildcard patterns with zero matches are skipped silently
  • RequiredFilesOptions.cs: Add HasWildcard computed property (checks for * or ? in Pattern); update MatchedPaths doc comment to describe the new distinction
  • README.md: Restore the "Disk check" bullet and SLNX020 row in the error codes table, both updated to describe the wildcard vs. literal distinction; update exit codes table
  • Tests: Split the no-match test into two cases — wildcard no-match (no error) and literal no-match (SLNX020); added matching ValidatorRunnerTests for both cases

Core logic:

if (matched is null || matched.Count == 0)
{
    if (!requiredFilesOptions.HasWildcard)
    {
        allErrors.Add(new ValidationError(ValidationErrorCode.RequiredFileDoesntExistOnSystem, ...));
    }
}
else
{
    // run reference check
}
Original prompt

Problem

In src/SLNX-validator/SlnxCollector.cs at line 64, when --required-files is used with a wildcard pattern that matches zero files, the code currently emits a SLNX020 (RequiredFileDoesntExistOnSystem) error:

var matched = requiredFilesOptions.MatchedPaths;
if (matched is null || matched.Count == 0)
{
    allErrors.Add(new ValidationError(
        ValidationErrorCode.RequiredFileDoesntExistOnSystem,
        $"Required file does not exist on the system. No files matched: {requiredFilesOptions.Pattern}"));
}

The desired behaviour: when a wildcard pattern matches 0 files, this should be considered valid (no error). Zero matches with a wildcard simply means there's nothing to check — treat it the same as if --required-files was not used for that solution. Only a non-wildcard (literal) pattern that matches nothing should produce the SLNX020 error.

Wait — re-reading the request: the user actually wants 0 items to always be OK for wildcards. Specifically the change is: remove the matched.Count == 0 branch (or change it so 0 matches is not an error at all). If the glob pattern yields 0 matches, just skip the check entirely (no SLNX020 error, no reference check either).

Required changes

1. src/SLNX-validator/SlnxCollector.cs (line 61–78)

Change the logic so that 0 matched files is not an error. Instead of:

if (requiredFilesOptions is not null)
{
    var matched = requiredFilesOptions.MatchedPaths;
    if (matched is null || matched.Count == 0)
    {
        allErrors.Add(new ValidationError(
            ValidationErrorCode.RequiredFileDoesntExistOnSystem,
            $"Required file does not exist on the system. No files matched: {requiredFilesOptions.Pattern}"));
    }
    else
    {
        var hasXsdErrors = allErrors.Any(e => e.Code == ValidationErrorCode.XsdViolation);
        if (!hasXsdErrors)
        {
            allErrors.AddRange(requiredFilesChecker.CheckInSlnx(matched, slnxFile));
        }
    }
}

It should become:

if (requiredFilesOptions is not null)
{
    var matched = requiredFilesOptions.MatchedPaths;
    if (matched is not null && matched.Count > 0)
    {
        var hasXsdErrors = allErrors.Any(e => e.Code == ValidationErrorCode.XsdViolation);
        if (!hasXsdErrors)
        {
            allErrors.AddRange(requiredFilesChecker.CheckInSlnx(matched, slnxFile));
        }
    }
}

2. src/SLNX-validator/RequiredFilesOptions.cs

Update the XML doc comment for MatchedPaths to reflect that an empty list is now valid (no error):

/// <param name="MatchedPaths">
/// Absolute disk paths that were matched by <see cref="Pattern"/>.
/// An empty list means the pattern matched no files — this is not an error (no files to check).
/// <see langword="null"/> means the <c>--required-files</c> option was not used.
/// </param>

3. README.md

Update the --required-files section. The "Disk check" bullet currently says:

  • Disk check — if no files match the glob patterns, a SLNX020 (RequiredFileDoesntExistOnSystem) error is added to the solution result.

This should be removed or updated to reflect that 0 matches is now OK and no error is emitted. Also update the SLNX020 row in the error codes table to clarify this code is no longer triggered by wildcard zero-matches (or simply remove it if it's entirely unused — but keep it if there are still scenarios where it fires; verify this in the code).

Also update the Exit codes table under --required-files:

Code Description
0 All matched files are referenced in the solution (or no files matched the pattern).
1 Any validation error — including required files not referenced.

4. Tests

  • Update tests/SLNX-validator.Tests/SlnxCollectorTests.cs: the test CollectAsync_RequiredFilesPatternNoMatch_AddsRequiredFileDoesntExistOnSystemError should be changed to assert no error (not SLNX020) when 0 files are matched, e.g. rename it to CollectAsync_RequiredFilesPatternNoMatch_NoError and assert HasErrors == false.
  • Add or update any other tests that verified the SLNX020 error being emitted for zero-match glob patterns.
  • If SLNX020 / RequiredFileDoesntExistOnSystem becomes entirely dead code (never emitted), consider removing it or keeping it with a note; be conservative and keep it unless it's clearly unused everywhere.

Check if SLNX020 is still used elsewhere before removing it. If it's only used in this one place (line 66 of SlnxCollector.cs), it becomes dead code and can be cleaned up, but only if you are confident it is not used anywhere else.

The following is the prior conversation context from the user's chat exploration (may be truncated):

User: Bij wildcards is 0 items prima. Dus dit aanpassen inclusief docs

if (matched is null || matched.Count == 0)
....

This pull request was created from Copilot chat.

Copilot AI changed the title [WIP] Fix SLNX020 error for wildcard patterns with zero matches fix: zero wildcard matches for --required-files is not an error Apr 7, 2026
Copilot AI requested a review from 304NotModified April 7, 2026 21:44
Copy link
Copy Markdown
Owner

@304NotModified 304NotModified left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is wrong. If we have unknownfile.md, we should an error. But not is *.unknown.file. So if it has a wildcard, then it's not required

… matches emit SLNX020

Agent-Logs-Url: https://github.com/304NotModified/SLNX-validator/sessions/deabf102-3e90-4a06-a252-62362daaa419

Co-authored-by: 304NotModified <5808377+304NotModified@users.noreply.github.com>
Copy link
Copy Markdown
Contributor Author

Copilot AI commented Apr 7, 2026

This is wrong. If we have unknownfile.md, we should an error. But not is *.unknown.file. So if it has a wildcard, then it's not required

Fixed in 22f975c. The logic now distinguishes between literal and wildcard patterns:

  • Literal (e.g. unknownfile.md, no */?) with 0 matches → SLNX020 error
  • Wildcard (e.g. *.md, **/*.yaml) with 0 matches → silently skipped, no error

Added HasWildcard property to RequiredFilesOptions (checks for * or ? in the pattern string) and updated docs and tests accordingly.

Copilot AI changed the title fix: zero wildcard matches for --required-files is not an error fix: zero wildcard matches for --required-files is not an error; literal non-matches emit SLNX020 Apr 7, 2026
Copilot AI requested a review from 304NotModified April 7, 2026 21:52
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants